﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace VerificationCode
{
    public partial class Form1 : Form
    {

        private string num1 = ""; //存放第一个数
        private string num2 = ""; //存放第二个数
        private string sign = ""; //存放运算符
        private string str = ""; //存放字符串

        private string num; //存储随机数
        private Point p; //坐标
        private Random rd;
        private Pen pen; //画笔
        private Graphics g; //GDI

        /// <summary>
        /// 画布，用于存放绘制的内容
        /// </summary>
        private Bitmap image; 

        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 程序运行时加载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            //创建随机数对象
            rd = new Random(DateTime.Now.Millisecond);

            //创建画布对象，大小为控件的大小
            image = new Bitmap(pbCode.Width, pbCode.Height);

            //绘制图片
            DrawImage();
        }

        /// <summary>
        /// 重置验证码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRestart_Click(object sender, EventArgs e)
        {
            #region 清空资源，参数
            pbCode.Image = null;
            image.Dispose();
            pen.Dispose();
            g.Dispose();
            txtChecked.Text = "";
            #endregion

            //因为释放了资源，所以重新创建新的画布对象，大小为控件的大小
            image = new Bitmap(pbCode.Width, pbCode.Height);

            //绘制图片
            DrawImage();

        }

        /// <summary>
        /// 验证输入内容的是否正确
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnChecked_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtChecked.Text))
            {
                MessageBox.Show("请输入验证码");
                return;
            }
            if (txtChecked.Text.Equals(num))
            {
                MessageBox.Show("验证成功");
                return;
            }
            else
            {
                MessageBox.Show("验证失败");
                return;
            }
        }

        /// <summary>
        /// 调用定义好的方法，绘制图片
        /// </summary>
        private void DrawImage()
        {
            //产生随机的数字
            VCode(ref num1, ref num2, ref sign);
            str = num1 + " " + sign + " " + num2;

            //产生随机的数，并绘制
            DrawNum(str);
            //产生随机的像素点，并绘制
            ErrorCode();
            //产生随机的线，并绘制
            DrawLine();
            
            //当全部绘制完成后，把这个图片放在控件上
            pbCode.Image = image;
        }

        /// <summary>
        /// 绘制像素点
        /// </summary>
        private void ErrorCode()
        {
            //循环200次绘制随机坐标的像素点
            for (int i = 0; i < 200; i++)
            {
                int R, G, B;
                RandomColor(out R, out G, out B);

                //绘制像素点
                image.SetPixel(rd.Next(0, image.Width), rd.Next(0, image.Height), Color.FromArgb(R, G, B));
            }
        }

        /// <summary>
        /// 绘制线条
        /// </summary>
        private void DrawLine()
        {
            //创建GDI对象，从画布开始绘制
            g = Graphics.FromImage(image);

            for (int i = 0; i < 20; i++)
            {
                //随机产生不同的颜色
                int R, G, B;
                RandomColor(out R, out G, out B);

                //创建画笔对象
                pen = new Pen(new SolidBrush(Color.FromArgb(150,R, G, B)), rd.Next(1, 5));
                
                //绘制线条
                g.DrawLine(pen, rd.Next(0, image.Width), rd.Next(0, image.Height), rd.Next(0, image.Width), rd.Next(0, image.Height));
            }
        }
        private void VCode(ref string num1, ref string num2, ref string sign)
        {
            #region 随机产生2个数和一个运算符
            num1 = ValidateCode.CreateVCode(rd.Next(1, 4));
            num2 = ValidateCode.CreateVCode(rd.Next(1, 4));
            sign = RandomOperation();
            #endregion
        }
        private void DrawNum(string str)
        {
            //创建一个新坐标
            p = new Point(rd.Next(0, image.Width-str.Length*9), rd.Next(0, image.Height-20));

            //创建GDI对象，从画布开始绘制
            g = Graphics.FromImage(image);

            

            //随机产生不同的颜色
            int R, G, B;
            RandomColor(out R, out G, out B);

            //绘制字符串
            g.DrawString(str, new Font("微软雅黑", rd.Next(10,16), FontStyle.Regular), new SolidBrush(Color.FromArgb(R, G, B)), p);

            //计算结果，然后存入全局变量
            num = Calculation(num1, num2, sign);
        }

        /// <summary>
        /// 随机产生颜色
        /// </summary>
        /// <param name="R"></param>
        /// <param name="G"></param>
        /// <param name="B"></param>
        private void RandomColor(out int R, out int G, out int B)
        {
            R = rd.Next(255);
            G = rd.Next(255);
            B = rd.Next(255);

            B = (R + G > 400) ? R + G - 400 : B;//0 : 380 - R - G;
            B = (B > 255) ? 255 : B;
        }

        /// <summary>
        /// 随机产生运算符
        /// </summary>
        /// <returns></returns>
        private string RandomOperation()
        {
            int num = rd.Next(0, 4);
            switch (num)
            {
                case 0:
                    return "+";
                case 1:
                    return "-";
                case 2:
                    return "*";
                case 3:
                    return "/";
            }
            return "";
        }

        /// <summary>
        /// 计算结果，传入参数，返回结果
        /// </summary>
        /// <param name="num1"></param>
        /// <param name="num2"></param>
        /// <param name="sign"></param>
        /// <returns></returns>
        private string Calculation(string num1,string num2,string sign)
        {
            string result = "";
            switch (sign)
            {
                case "+":
                    result = (Convert.ToInt32(num1) + Convert.ToInt32(num2)).ToString();
                    return result;
                case "-":
                    result = (Convert.ToInt32(num1) - Convert.ToInt32(num2)).ToString();
                    return result;
                case "*":
                    result = (Convert.ToInt32(num1) * Convert.ToInt32(num2)).ToString();
                    return result;
                case "/":
                    if (Convert.ToInt32(num2) != 0)
                    {
                        result = (Convert.ToInt32(num1) / Convert.ToInt32(num2)).ToString();
                    }
                    else
                    {
                        result = "0";
                    }
                    return result;
            }
            return result;
        }
    }
}
